This is an R Markdown Notebook. RMD available here (https://github.com/ghettocounselor/R_Investing/blob/master/PracticalDataScience_AnalyzingStocks_IndicatorsPUB.Rmd)
using quantmod from Cran (https://cran.r-project.org/web/packages/quantmod/)
# install.packages('quantmod')
library(quantmod)
Loading required package: xts
Loading required package: zoo
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
Loading required package: TTR
Version 0.4-0 included new data defaults. See ?getSymbols.
Learn from a quantmod author: https://www.datacamp.com/courses/importing-and-managing-financial-data-in-r
For various elements have a look at quantmod
?quantmod
We’ll use Yahoo here but Google Finance is also supported. Syntax is slightly different. (https://finance.yahoo.com/lookup/)
We’ll call multiple symbols at once by creating a vector of symbols and then pass the basket to the getSymbols function.
symbolBasket <- c('AAPL', 'AMZN', 'BRK-B', 'SPY')
getSymbols(symbolBasket , src='yahoo')
‘getSymbols’ currently uses auto.assign=TRUE by default, but will
use auto.assign=FALSE in 0.5-0. You will still be able to use
‘loadSymbols’ to automatically load data. getOption("getSymbols.env")
and getOption("getSymbols.auto.assign") will still be checked for
alternate defaults.
This message is shown once per session and may be disabled by setting
options("getSymbols.warning4.0"=FALSE). See ?getSymbols for details.
[1] "AAPL" "AMZN" "BRK-B" "SPY"
Summary will show us basics; notice we have to use `` for funny charcters.
summary(`BRK-B`)
Index BRK-B.Open BRK-B.High BRK-B.Low
Min. :2007-01-03 Min. : 45.08 Min. : 47.7 Min. : 44.82
1st Qu.:2010-02-03 1st Qu.: 78.65 1st Qu.: 79.3 1st Qu.: 77.94
Median :2013-03-07 Median :102.14 Median :102.7 Median :101.89
Mean :2013-03-06 Mean :116.22 Mean :117.0 Mean :115.31
3rd Qu.:2016-04-07 3rd Qu.:145.10 3rd Qu.:145.7 3rd Qu.:144.19
Max. :2019-05-10 Max. :224.00 Max. :224.1 Max. :221.30
BRK-B.Close BRK-B.Volume BRK-B.Adjusted
Min. : 46.00 Min. : 175000 Min. : 46.00
1st Qu.: 78.78 1st Qu.: 2240325 1st Qu.: 78.78
Median :102.25 Median : 3295750 Median :102.25
Mean :116.20 Mean : 3707459 Mean :116.20
3rd Qu.:144.92 3rd Qu.: 4388225 3rd Qu.:144.92
Max. :223.76 Max. :316134200 Max. :223.76
NOTE: BRK-B IS ODD so we cannot get away from data prep ;-) ‘rename’ the object BRK-B to BRKB, not really rename but in essence. Then change names of ‘names’ in new BRKB object
BRKB <- as.xts(`BRK-B`)
names(BRKB)
[1] "BRK-B.Open" "BRK-B.High" "BRK-B.Low" "BRK-B.Close"
[5] "BRK-B.Volume" "BRK-B.Adjusted"
names(BRKB) <- c("BRKB.Open" , "BRKB.High" , "BRKB.Low" , "BRKB.Close" , "BRKB.Volume", "BRKB.Adjusted")
names(BRKB)
[1] "BRKB.Open" "BRKB.High" "BRKB.Low" "BRKB.Close" "BRKB.Volume"
[6] "BRKB.Adjusted"
plot(BRKB$BRKB.Open)
To view some variation on this a bit we can use this code;
lineChart(BRKB$BRKB.Open, line.type = 'h', theme = 'white', TA = NULL)
To see volumes; remove the TA
lineChart(BRKB, line.type = 'h', theme = 'white')
Barchart, type allows for high, low, close ;)
barChart(BRKB, bar.type = 'hlc', TA = NULL)
Now just a subset and in candle sticks
candleChart(BRKB, TA=NULL, subset = '2019')
Give a look to candleChart for features;
?candleChart
getSymbols(“YHOO”) chartSeries(YHOO) chartSeries(YHOO, subset=‘last 4 months’) chartSeries(YHOO, subset=‘2007::2008-01’) chartSeries(YHOO,theme=chartTheme(‘white’)) chartSeries(YHOO,TA=NULL) #no volume chartSeries(YHOO,TA=c(addVo(),addBBands())) #add volume and Bollinger Bands from TTR
NOTE there are a ton of add… items that are very slick
addMACD() # add MACD indicator to current chart
setTA() chartSeries(YHOO) #draws chart again, this time will all indicators present
Add MACD
candleChart(BRKB, TA=c(addMACD(),addVo()), subset = '2019')
?addMACD
?addMACD()
addMACD(fast = 12, slow = 26, signal = 9, type = “EMA”, histogram = TRUE, col)
Various ways to dictate time, in this case everything after… Also added in ADX
candleChart(BRKB, TA=c(addMACD(),addADX()), subset = '2018-01::')
Various ways to dictate time, in this case everything in between… Background is the ‘Theme’
candleChart(BRKB , TA=c(addMACD()), subset = '2018-01::2018-05', theme = 'white')
Various options for theme’s overall
candleChart(BRKB , TA=c(addMACD()), subset = '2019-01::', theme = chartTheme('white', up.col='green',dn.col='darkred'))
chartSeries is another cool way to do this same stuff
?chartSeries
chartSeries(BRKB,
type = c("auto", "candlesticks"),
subset = '2019-01::',
show.grid = TRUE,
major.ticks='auto', minor.ticks=TRUE,
TA=c(addMACD(),addVo()))
chartSeries(BRKB,
type = c("auto", "candlesticks"),
subset = '2018-01::',
show.grid = TRUE,
major.ticks='auto', minor.ticks=TRUE,
multi.col = TRUE,
TA=c(addMACD(),addVo()))
chartSeries(BRKB,
type = c("auto", "matchsticks"),
subset = '2018-01::',
show.grid = TRUE,
major.ticks='auto', minor.ticks=TRUE,
multi.col = TRUE,
TA=c(addMACD(),addVo()))
We’ll use TTR, which is installed with quantmod, if not you can install TTR TTR - Technical Trading Rules So Cool!
?TTR
Let’s do a Simple Moving Average
chartSeries(BRKB,
type = c("auto", "matchsticks"),
subset = '2018-01::',
show.grid = TRUE,
major.ticks='auto', minor.ticks=TRUE,
multi.col = FALSE,
TA=c(addMACD(),addVo(),addSMA(n=200,col = 'blue'),addSMA(n=50,col = 'red'),addSMA(n=22,col = 'green'),
addROC(n=200,col = 'blue'),addROC(n=50,col = 'red'),addROC(n=22,col = 'green'))) # rate of change
Bollinger bands Basics; addBBands(n = 20, sd = 2, maType = “SMA”, draw = ‘bands’, on = -1)
?addBBands
Experimental BBands “The primary addition to this function call over the TTR version is in the draw argument. ‘bands’ will draw standard Bollinger Bands, ‘percent’ will draw Bollinger %b and ‘width’ will draw Bolinger Bands Width. The last two will be drawn in new figure regions.”
?add_BBands
chartSeries(BRKB, theme="white",
TA="addVo();addBBands();addCCI()", subset = '2018-01::')
chartSeries(BRKB, theme="white",
TA="addVo();addBBands();addCCI()", subset = '2018-01::')
Start with a simple chart.
chartSeries(BRKB, theme=chartTheme('white'), up.col="black",
dn.col="black")
CREATE two vectors as a time series to make a Exponential Moving Average. EMA is like a SMA except it gives more weight to the recent activity and that means it tends to mimic the market a little better.
BRKB exponential moving averages
BRKB.EMA.20<- EMA(BRKB$BRKB.Close, n=20)
BRKB.EMA.50<- EMA(BRKB$BRKB.Close, n=50)
BRKB.EMA.100<- EMA(BRKB$BRKB.Close, n=100)
BRKB.EMA.200<- EMA(BRKB$BRKB.Close, n=200)
chartSeries(BRKB, theme=chartTheme('white'),
type = c("auto", "matchsticks"),
subset = '2018-01::',
show.grid = TRUE,
major.ticks='auto', minor.ticks=TRUE,
multi.col = FALSE,
TA=c(addMACD(),addVo(),addADX(n = 14, maType = "EMA")))
addTA(BRKB.EMA.20, on=1, col = "green")
addTA(BRKB.EMA.50, on=1, col = "blue")
addTA(BRKB.EMA.100, on=1, col = "yellow")
addTA(BRKB.EMA.200, on=1, col = "red")
addTA(BRKB.EMA.20 - BRKB.EMA.200, col = "black",
type = 'h', legend = "100-200 EMA")
library(quantmod)
getSymbols(c('QQQ'), src='yahoo')
[1] "QQQ"
Plot the graph of the triple Q’s
plot(QQQ$QQQ.Close)
We choose a period, which sets the number of points of data that will be required to create one point of raw data (averaged) to get a point of data in our visualization. The price_vector is the group of data we want to use.
period <- 100
price_vector <- QQQ$QQQ.Close
length(price_vector)
[1] 3110
Now we need a vector to put our values into, so we’ll define an empty vector that we’ll then make a loop through our price_vector to fille the vector
moving_average_vector <- c()
Let’s look at sequence to understand : and ,
seq(5:10) # note that sequence gives us the number of values between 5 and 10 ;)
[1] 1 2 3 4 5 6
seq(5,10) # this sequence gives us from 5 to 10
[1] 5 6 7 8 9 10
The ‘Loop’. Let’s have a look at how this comes together.
for (ind in seq(period:length(price_vector))) { # so, period starts at 1 due to :
print(ind)
break # to stop it at the first go
}
[1] 1
Let’s fix that with a comma
for (ind in seq(period,length(price_vector))) { # period is 100
print(ind)
break # to stop it at the first go
}
[1] 100
Now, because we want to use 100 values as the period we need to start at 100 + 1, and we need parens. And we now can start the code to assign the values to the new empty vector.
for (ind in seq((period + 1),length(price_vector))) {
moving_average_vector <- c(moving_average_vector, # here we are saying add the mean to
# the moving_average_vector
mean(price_vector[(ind - period):ind])) #
}
head(moving_average_vector)
[1] 44.66208 44.70119 44.73436 44.76990 44.80653 44.84099
tail(moving_average_vector)
[1] 171.7212 172.0040 172.2334 172.4528 172.6480 172.8450
summary(moving_average_vector)
Min. 1st Qu. Median Mean 3rd Qu. Max.
29.24 47.79 68.44 84.63 108.86 178.97
moving_average_vector[1:100] # show 100 items
[1] 44.66208 44.70119 44.73436 44.76990 44.80653 44.84099 44.86525 44.87772 44.89356
[10] 44.90881 44.92495 44.95436 44.98594 45.02624 45.06772 45.10198 45.13743 45.17871
[19] 45.21515 45.24941 45.27663 45.31168 45.34495 45.37941 45.41871 45.45683 45.49851
[28] 45.54782 45.59911 45.64485 45.68653 45.73307 45.78446 45.83198 45.88188 45.92891
[37] 45.97901 46.02861 46.09673 46.15614 46.21822 46.28257 46.34040 46.39683 46.44485
[46] 46.49366 46.54723 46.58891 46.64436 46.69703 46.75594 46.80426 46.84396 46.88376
[55] 46.90723 46.92347 46.93663 46.95653 46.98168 47.01634 47.05683 47.09644 47.14208
[64] 47.17891 47.20267 47.23752 47.27594 47.31743 47.37158 47.41733 47.46178 47.49317
[73] 47.52327 47.56208 47.59960 47.63703 47.67416 47.70495 47.74188 47.77772 47.81198
[82] 47.85554 47.90178 47.94782 47.99465 48.04366 48.09099 48.14317 48.19446 48.24851
[91] 48.29792 48.36089 48.43069 48.49832 48.56941 48.62832 48.69287 48.75297 48.81277
[100] 48.88594
We can see from above what has happened. We have, started with the first 100 recalculated the mean with each 100 previous values, all the way to the end.
Let’s graph a few things.
par(mfrow=c(2,1)) # gives us two graphs, one on top of another
plot(QQQ$QQQ.Close)
plot(moving_average_vector, type = 'l', col = 'red', lwd=3,
main = paste('SMA', period))
Let’s check the length. We can see that we gave up that 100 to calculate the mean given the period of 100. This means however that we cannot graph the two against one another because they are different sizes.
length(price_vector)
[1] 3110
length(moving_average_vector)
[1] 3010
Let’s fix that; We’ll play a little trick and fill in those first 100 characters with NA using the repeat function. Here we say give me 100 NA’s
rep(NA, period)
[1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[28] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[55] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[82] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
So, instead of starting moving_average_vector as a blank vector we’ll start with 100 NA’s, or whatever the period is.
period <- 100
price_vector <- QQQ$QQQ.Close
moving_average_vector <- c(rep(NA, period))
for (ind in seq((period + 1),length(price_vector))) {
moving_average_vector <- c(moving_average_vector, # here we are saying add the mean to
# the moving_average_vector
mean(price_vector[(ind - period):ind])) #
}
Check the length. Bingo.
length(moving_average_vector)
[1] 3110
length(price_vector)
[1] 3110
Now we can add our moving average to the XTS object of the QQQ’s.
QQQ$QQQ.Close.SMA <- moving_average_vector
names(QQQ)
[1] "QQQ.Open" "QQQ.High" "QQQ.Low" "QQQ.Close" "QQQ.Volume"
[6] "QQQ.Adjusted" "QQQ.Close.SMA"
Let’s graph the close and the new SMA.
plot(QQQ$QQQ.Close)
lines(QQQ$QQQ.Close.SMA, type = 'l', col = 'red', lwd = 6)
Let’s call the same thing from TTR package ;) We’ll use fresh data. Same thing 2 lines of code.
getSymbols(c('QQQ'), src = 'yahoo')
[1] "QQQ"
chartSeries(QQQ, theme='white', TA="addSMA(100)")
Basics of code behind what is shown.